/**
 * 
 */
package edu.gtcfla.km.admin.appmodules.web;

import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.ListIterator;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import net.sf.json.JSONArray;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;

import org.apache.commons.io.IOUtils;
import org.apache.shiro.authz.annotation.RequiresUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.vsg.common.i18n.I18nMessageService;
import org.vsg.common.web.json.ListResult;
import org.vsg.common.web.json.SelectItem;
import org.vsg.common.web.json.SubmitResult;
import org.vsg.common.web.json.processor.JsDateViewJsonValueProcessor;
import org.vsg.security.annotation.RegisterRequestPermissionStrategy;

import edu.gtcfla.km.admin.appmodules.service.FunctionManagerService;
import edu.gtcfla.km.admin.appmodules.service.ModuleManagerService;
import edu.gtcfla.km.admin.appmodules.vo.DisabledOptionItem;
import edu.gtcfla.km.admin.appmodules.vo.ModuleEditionVO;
import edu.gtcfla.km.admin.appmodules.vo.ModuleFunctionInModuleVO;
import edu.gtcfla.km.admin.appmodules.vo.ModuleFunctionPermissionVO;
import edu.gtcfla.km.admin.appmodules.vo.ModuleFunctionVO;
import edu.gtcfla.km.admin.appmodules.vo.ModulePermissionVO;
import edu.gtcfla.km.core.ApplicationConstant;

/**
 * @author Bill vison
 *
 */
@Controller
@Lazy
@RequestMapping(ApplicationConstant.DATA_RERESOURCE)
public class ModuleController {
	
	private final static Logger logger = LoggerFactory.getLogger(ModuleController.class);	

	
	private final String modulePrefix = "/resources";
	
	@Autowired(required =false)
	private ModuleManagerService moduleManagerService;
	
	@Autowired(required =false)
	private I18nMessageService i18nMessageService;	
	
	@Autowired(required =false)	
	private FunctionManagerService moduleFunctionService;
	

	
	@RequiresUser
	@RegisterRequestPermissionStrategy(
		value = "/resources/module/list_funs.json",
		skipCheck = true
	)
	@RequestMapping(value = modulePrefix + "/module/list_funs.json")
	public @ResponseBody ListResult accessModuleFunctionlist(String modResId)
			throws Exception {

		
		ListResult listResult = new ListResult();
		Set<ModuleFunctionInModuleVO> funs = new LinkedHashSet<ModuleFunctionInModuleVO>();
	
		if (modResId != null) {
			funs =  moduleManagerService.findFunsByModResId( modResId );
		}
		listResult.setRows( funs );
		listResult.setResults( funs.size() );		
        
		return listResult;

	}

	@RequiresUser
	@RegisterRequestPermissionStrategy(
		value = "/resources/module/reg_paging.json",
		skipCheck = true
	)	
	@RequestMapping(value =  modulePrefix + "/module/reg_paging.json")
	public @ResponseBody ListResult accessPageModule()
			throws Exception {

		// --- map to json object data ---
		
		Set<ModuleEditionVO> allModules = moduleManagerService.findAllModules();

		ListResult listResult = new ListResult();
		listResult.setRows( allModules );
		listResult.setResults( allModules.size() );

		return listResult;

	}

	@RequiresUser
	@RegisterRequestPermissionStrategy(
		value = "list_unloadModules.json",
		skipCheck = true
	)	
	@RequestMapping(value = ApplicationConstant.DATA_RERESOURCE + "/list_unloadModules.json")
	public ModelAndView accessOfUnloadedModulelist()
			throws Exception {

		// --- map to json object data ---
		
		Set<ModuleEditionVO> allModules = moduleManagerService.findUnloadedModules();

		ListResult listResult = new ListResult();
		listResult.setRows( allModules );
		listResult.setResults( allModules.size() );
		
		JsonConfig jcfg = new JsonConfig();	
		jcfg.registerJsonValueProcessor(java.util.Date.class,new JsDateViewJsonValueProcessor());
		JSONObject jsonObject = JSONObject.fromObject(listResult, jcfg);		

		ModelAndView mav = new ModelAndView();
		mav.addObject("json", jsonObject);
		mav.setViewName("result"); // view name

        
		return mav;

	}	
	
	@RequiresUser
	@RegisterRequestPermissionStrategy(
		value = "unableModule.json",
		skipCheck = true
	)
	@RequestMapping(value = ApplicationConstant.DATA_RERESOURCE + "/unableModule.json")
	public ModelAndView accessOfUnregisterAllRes(String jsonData)
			throws Exception {

		// --- map to json object data ---
		// --- map to json object data ---
		SubmitResult result = new SubmitResult();
		if (jsonData == null ) {
			result.setSuccess( false );
			String msg = i18nMessageService.getMessage("crm.module-uninstall.resources.error", null);
			result.setMsg(msg);					
		} else {

			JSONObject jsonObj = JSONObject.fromObject( jsonData );
			
			String resId = jsonObj.getString("resId");
			String moduleId = jsonObj.getString("moduleId");
			
			//boolean unRegAllRes = registerResourceService.unregisterAllResource(resId, moduleId);

			result.setSuccess(true);
			String msg = i18nMessageService.getMessage("crm.module-uninstall.resources.success", null);
			result.setMsg(msg);
			
		}
		
		JsonConfig jcfg = new JsonConfig();	
		jcfg.registerJsonValueProcessor(java.util.Date.class,new JsDateViewJsonValueProcessor());
		JSONObject jsonObject = JSONObject.fromObject(result, jcfg);		


		ModelAndView mav = new ModelAndView();
		mav.addObject("json", jsonObject);
		mav.setViewName("result"); // view name

        
		return mav;

	}
		
	@RequiresUser
	@RegisterRequestPermissionStrategy(
		value = "enableModule.json",
		skipCheck = true
	)
	@RequestMapping(value = ApplicationConstant.DATA_RERESOURCE +"/enableModule.json")
	public ModelAndView enableModule(String jsonData)
			throws Exception {

		// --- map to json object data ---
		SubmitResult result = new SubmitResult();
		if (jsonData == null ) {
			result.setSuccess( false );
			String msg = i18nMessageService.getMessage("crm.module-install.resources.error", null);
			result.setMsg(msg);					
		} else {

			JSONObject jsonObj = JSONObject.fromObject( jsonData );
			
			String resId = jsonObj.getString("resId");
			String moduleId = jsonObj.getString("moduleId");
			
			//boolean regAllRes = registerResourceService.registerAllResource(resId, moduleId);

			result.setSuccess(true);
			String msg = i18nMessageService.getMessage("crm.module-install.resources.success", null);
			result.setMsg(msg);
			
		}
		
		JsonConfig jcfg = new JsonConfig();	
		jcfg.registerJsonValueProcessor(java.util.Date.class,new JsDateViewJsonValueProcessor());
		JSONObject jsonObject = JSONObject.fromObject(result, jcfg);		


		ModelAndView mav = new ModelAndView();
		mav.addObject("json", jsonObject);
		mav.setViewName("result"); // view name

        
		return mav;

	}

	@RequiresUser
	@RegisterRequestPermissionStrategy(
		value = "modulelist_auth.json",
		skipCheck = true
	)
	@RequestMapping(value = ApplicationConstant.DATA_RERESOURCE +"/modulelist_auth.json")
	public ModelAndView accessModuleListAuth(String roleId) throws Exception {
		
		
		Set<ModulePermissionVO> permissionModuleSet = new LinkedHashSet<ModulePermissionVO>();
		if (roleId == null || roleId.equals("")) {
			logger.info("prameter roleid is " + roleId);
		} else {
			// --- find all module ---
			permissionModuleSet =  moduleManagerService.listPermissionModulesByRoleId( roleId);
			
		}

		ListResult listResult = new ListResult();
		listResult.setRows( permissionModuleSet );
		listResult.setResults( permissionModuleSet.size() );
		
		JsonConfig jcfg = new JsonConfig();	
		jcfg.registerJsonValueProcessor(java.util.Date.class,new JsDateViewJsonValueProcessor());
		JSONObject jsonObject = JSONObject.fromObject(listResult, jcfg);			
		
		ModelAndView mav = new ModelAndView();
		mav.addObject("json", jsonObject);
		mav.setViewName("result"); // view name

		return mav;
	}		
	
	@RequiresUser
	@RegisterRequestPermissionStrategy(
		value = "modulefunctionlist_auth.json",
		skipCheck = true
	)	
	@RequestMapping(value = ApplicationConstant.DATA_RERESOURCE + "/modulefunctionlist_auth.json")
	public ModelAndView accessModuleFunctionListAuth(String roleId , String moduleId) throws Exception {
		
		
		Set<ModuleFunctionPermissionVO> permFunsSet = new LinkedHashSet<ModuleFunctionPermissionVO>();
		if (roleId == null || roleId.equals("")  || moduleId == null || moduleId.equals("") ) {
			logger.info("prameter roleid is " + roleId + " , " + " module is is " + moduleId);
		} else {
			// --- find all module ---
			permFunsSet =  this.moduleFunctionService.listPermissionFunsByRoleId(roleId, moduleId);
			
		}

		ListResult listResult = new ListResult();
		listResult.setRows( permFunsSet );
		listResult.setResults( permFunsSet.size() );
		
		JsonConfig jcfg = new JsonConfig();	
		jcfg.registerJsonValueProcessor(java.util.Date.class,new JsDateViewJsonValueProcessor());
		JSONObject jsonObject = JSONObject.fromObject(listResult, jcfg);			
		
		ModelAndView mav = new ModelAndView();
		mav.addObject("json", jsonObject);
		mav.setViewName("result"); // view name

		return mav;
	}		

	
	
	@RequiresUser
	@RegisterRequestPermissionStrategy(
		value = "select_ChecksOfFunInModule.json",
		skipCheck = true
	)
	@RequestMapping(value = ApplicationConstant.DATA_RERESOURCE + "/select_ChecksOfFunInModule.json")
	public ModelAndView accessSelectChecksOfFunInModule() throws Exception {
		
		
		Set<DisabledOptionItem> optItems = new LinkedHashSet<DisabledOptionItem>();
		
		DisabledOptionItem enableItem = new DisabledOptionItem();
		enableItem.setValue(true);
		enableItem.setName("禁用");
		
		optItems.add( enableItem );

		DisabledOptionItem disableItem = new DisabledOptionItem();
		disableItem.setName("启用");
		optItems.add( disableItem );
		
		JsonConfig jcfg = new JsonConfig();	
		jcfg.registerJsonValueProcessor(java.util.Date.class,new JsDateViewJsonValueProcessor());
		JSONArray jsonObject = JSONArray.fromObject(optItems, jcfg);		

		

		ModelAndView mav = new ModelAndView();
		mav.addObject("json", jsonObject);
		mav.setViewName("result"); // view name
        
		return mav;
	}
	
	@RequiresUser
	@RegisterRequestPermissionStrategy(
		value = "update_funsInModule.json",
		skipCheck = true
	)
	@RequestMapping(value = ApplicationConstant.DATA_RERESOURCE + "/update_funsInModule.json", method = {RequestMethod.POST , RequestMethod.GET})	
	public ModelAndView accessUpdateFunsInModule(HttpServletRequest request) throws Exception {

		String jsonData = IOUtils.toString( request.getInputStream() );		
		
		// --- map to json object data ---
		SubmitResult result = new SubmitResult();
		if (jsonData == null ) {
			
			result.setSuccess( false );
			String msg = i18nMessageService.getMessage("module-admin.module.updatefunction.status.success", null);
			result.setMsg(msg);
			
		} else {

			Set<String> ignoreProperties = new LinkedHashSet<String>();
			ignoreProperties.add("locked");
			ignoreProperties.add("code");
			ignoreProperties.add("classname");
			ignoreProperties.add("deleted");
			ignoreProperties.add("moduleId");
			ignoreProperties.add("permissions");
			ignoreProperties.add("remark");
			ignoreProperties.add("createdUserId");
			ignoreProperties.add("createdDate");
			ignoreProperties.add("name");
			ignoreProperties.add("sysModule");
			ignoreProperties.add("bindingActions");			
			
			try {

				JSONArray jsonArray = JSONArray.fromObject( jsonData );			
				

				ListIterator<JSONObject> li = (ListIterator<JSONObject>) jsonArray.listIterator();
				
				Set<ModuleFunctionVO> modFuns = new LinkedHashSet<ModuleFunctionVO>();

				while ( li.hasNext() ) {
					
					JSONObject items = li.next();
					
					String id = items.getString("id");
					String name = items.getString("name");
					boolean disalbed = items.getBoolean( "disabled" );
					
					ModuleFunctionVO modFunVO = new ModuleFunctionVO();
					modFunVO.setId( id );
					modFunVO.setDisabled(  disalbed ? (short)1 : 0 );
					modFuns.add( modFunVO );
				}
				
				moduleFunctionService.updateAllFunctions(modFuns, ignoreProperties.toArray(new String[0]));
				
			} catch (JSONException jsonE) {
				// --- parse json object ---
				if (jsonE.getMessage().startsWith("A JSONArray text must start with '['") ) {
					
					JSONObject jsonObj = JSONObject.fromObject(jsonData);
					
					String id = jsonObj.getString("id");
					String name = jsonObj.getString("name");
					boolean disalbed = jsonObj.getBoolean( "disabled" );
					
					ModuleFunctionVO modFunVO = new ModuleFunctionVO();
					modFunVO.setId( id );
					modFunVO.setDisabled(  disalbed ? (short)1 : 0 );
					
					moduleFunctionService.update(modFunVO, ignoreProperties.toArray(new String[0]));
				}
			}


			
			// --- remove user id ---
			try {
				
				result.setSuccess(true);
				String msg = i18nMessageService.getMessage("module-admin.module.updatefunction.status.success", null);
				result.setMsg(msg);
				
			} catch (Exception se) {
				// TODO Auto-generated catch block
				se.printStackTrace();
				result.setSuccess(false);
				String msg = i18nMessageService.getMessage("module-admin.module.updatefunction.status.error", null);
				result.setMsg(msg);				
			}
			
		}
	
		

		
		JsonConfig jcfg = new JsonConfig();	
		jcfg.registerJsonValueProcessor(java.util.Date.class,new JsDateViewJsonValueProcessor());
		JSONArray jsonObject = JSONArray.fromObject(new HashSet(), jcfg);		
		
		ModelAndView mav = new ModelAndView();
		mav.addObject("json", jsonObject);
		mav.setViewName("result"); // view name
        
		return mav;		
	}
	
	@RequiresUser
	@RegisterRequestPermissionStrategy(
		value = modulePrefix + "/module/all_select.json",
		skipCheck = true
	)
	@RequestMapping(value = modulePrefix + "/module/all_select.json")
	public @ResponseBody Set<SelectItem> accessAllSelect()
			throws Exception {

		Set<SelectItem> allMods = moduleManagerService.findAllSelModule();
        
		return allMods;

	}	
	
}
